#include "pitches.h" //包含了常用的音符频率

#define NUM 7       //触控引脚的数量
#define CAP_VALUE 2 //cap的阈值
// int ledPin = 13; //test led pin
int buzzerPin = 16;                                                                 //蜂鸣器引脚
int touchPin[NUM] = {4, 5, 6, 7, 8, 9, 10};                                         //电子琴引脚 tone()函数时会影响引脚3和引脚11的PWM信号输出
int toneVal[NUM] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4}; //C调 中音 1~7
int duration = 300;                                                                 // 1/4拍的持续时间 ms

int capVal[NUM]; //引脚电容检测到的值
int lastPin = 0; //记录下当前触摸有效的按钮 方便使能和去使能

void setup()
{
    // pinMode(ledPin, OUTPUT);
    pinMode(buzzerPin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Touch senser");
}

void loop()
{
    // digitalWrite(ledPin, LOW);
    boolean isPin = false; //当前如果有引脚被触摸，就置位true,反之被置位false;

    for (int i = 0; i < NUM; i++)
    {
        int capval = readCapacitivePin(touchPin[i]); //记录下获取到的每个引脚的电容值
        Serial.println(capval);

        if (capval > CAP_VALUE)
        {
            // turn LED on:
            // digitalWrite(ledPin, HIGH);
            if (touchPin[i] != lastPin) //如果当上次的引脚和这次的不一样，就先noTone
            {
                isPin = true;
                tone(buzzerPin, toneVal[i]); //这里需要让tone持续一个节拍后停止，所以也要加持续时间；
                delay(duration);             //tone函数用的是中断，想让代码停在这里还是得用delay
                break;                       //为简化功能，一次只响应一个按键，所以用break;
            }
            else //如果一样，就不做任何操作，继续响一个节拍
            {
                tone(buzzerPin, toneVal[i]);
                delay(duration);
                break;
            }
        }
    }

    if (!isPin)
    {
        noTone(buzzerPin); //遍历一遍如果没有引脚被按下，就关掉声音
    }

    // Serial.println(capval, DEC); //DEC 十进制
}

uint8_t readCapacitivePin(int pinToMeasure)
{
    // Variables used to translate from Arduino to AVR pin naming
    volatile uint8_t *port;
    volatile uint8_t *ddr;
    volatile uint8_t *pin;
    // Here we translate the input pin number from
    // Arduino pin number to the AVR PORT, PIN, DDR,
    // and which bit of those registers we care about.
    byte bitmask;
    port = portOutputRegister(digitalPinToPort(pinToMeasure));
    ddr = portModeRegister(digitalPinToPort(pinToMeasure));
    bitmask = digitalPinToBitMask(pinToMeasure);
    pin = portInputRegister(digitalPinToPort(pinToMeasure));
    // Discharge the pin first by setting it low and output
    *port &= ~(bitmask);
    *ddr |= bitmask;
    delay(1);
    // Make the pin an input with the internal pull-up on
    *ddr &= ~(bitmask);
    *port |= bitmask;

    // Now see how long the pin to get pulled up. This manual unrolling of the loop
    // decreases the number of hardware cycles between each read of the pin,
    // thus increasing sensitivity.
    uint8_t cycles = 17;
    if (*pin & bitmask)
    {
        cycles = 0;
    }
    else if (*pin & bitmask)
    {
        cycles = 1;
    }
    else if (*pin & bitmask)
    {
        cycles = 2;
    }
    else if (*pin & bitmask)
    {
        cycles = 3;
    }
    else if (*pin & bitmask)
    {
        cycles = 4;
    }
    else if (*pin & bitmask)
    {
        cycles = 5;
    }
    else if (*pin & bitmask)
    {
        cycles = 6;
    }
    else if (*pin & bitmask)
    {
        cycles = 7;
    }
    else if (*pin & bitmask)
    {
        cycles = 8;
    }
    else if (*pin & bitmask)
    {
        cycles = 9;
    }
    else if (*pin & bitmask)
    {
        cycles = 10;
    }
    else if (*pin & bitmask)
    {
        cycles = 11;
    }
    else if (*pin & bitmask)
    {
        cycles = 12;
    }
    else if (*pin & bitmask)
    {
        cycles = 13;
    }
    else if (*pin & bitmask)
    {
        cycles = 14;
    }
    else if (*pin & bitmask)
    {
        cycles = 15;
    }
    else if (*pin & bitmask)
    {
        cycles = 16;
    }

    // Discharge the pin again by setting it low and output
    // It's important to leave the pins low if you want to
    // be able to touch more than 1 sensor at a time - if
    // the sensor is left pulled high, when you touch
    // two sensors, your body will transfer the charge between
    // sensors.
    *port &= ~(bitmask);
    *ddr |= bitmask;

    return cycles;
}